//组合模式，将对象组合成树状结构，以表示部分和整体的关系
//组合模式使得用户对单个对象和组合对象的使用具有一致性
//可用于描述树状结构
#include <iostream>
#include <memory>
#include <list>
#include <string>

class AbstractCompany
{
public:
    using ptr = std::shared_ptr<AbstractCompany>;
    AbstractCompany(const std::string &name) : m_name(name) {}
    virtual void addDepartment(AbstractCompany::ptr department) = 0;
    virtual void removeDepartment(AbstractCompany::ptr department) = 0;
    virtual void displayDepartment(int depth) = 0;
    virtual void showDuty() = 0;
protected:
    std::string m_name;
};

class Company: public AbstractCompany
{
public:
    using ptr=std::shared_ptr<Company>;
    Company(const std::string &name) : AbstractCompany(name) {}
    virtual void addDepartment(AbstractCompany::ptr department) override
    {
        m_departments.push_back(department);
    }
    virtual void removeDepartment(AbstractCompany::ptr department) override
    {
        m_departments.remove(department);
    }
    virtual void displayDepartment(int depth) override
    {
        std::cout<<std::string(depth,'-')<<AbstractCompany::m_name<<std::endl;
        for(const auto& item:m_departments){
            item->displayDepartment(depth+2);
        }
    }
    virtual void showDuty() override
    {
        std::cout<<"这个一个公司，分公司也是公司"<<std::endl;
    }
private:
    std::list<AbstractCompany::ptr> m_departments;
};

class Financial : public AbstractCompany
{
public:
    using ptr = std::shared_ptr<Financial>;
    Financial(const std::string &name) : AbstractCompany(name) {}
    void addDepartment(AbstractCompany::ptr department) override
    {
        std::cout<<"这是财务处，这不能加部门"<<std::endl;
    }
    void removeDepartment(AbstractCompany::ptr department) override
    {
        std::cout<<"这是财务处,不能减部门,要减部门，你把我减掉吧"<<std::endl;
    }
    void displayDepartment(int depth) override
    {
        std::cout<<std::string(depth,'-')<<AbstractCompany::m_name<<std::endl;
    }
    void showDuty() override
    {
        std::cout<<"我是财务处，我负责管钱"<<std::endl;
    }
};

class HumanResouce:public AbstractCompany
{
    public:
    using ptr = std::shared_ptr<HumanResouce>;
    HumanResouce(const std::string &name) : AbstractCompany(name) {}
    void addDepartment(AbstractCompany::ptr department) override
    {
        std::cout<<"这是人力处，这不能加部门"<<std::endl;
    }
    void removeDepartment(AbstractCompany::ptr department) override
    {
        std::cout<<"这是人力处,不能减部门,要减部门,我先把你裁了"<<std::endl;
    }
    void displayDepartment(int depth) override
    {
        std::cout<<std::string(depth,'-')<<AbstractCompany::m_name<<std::endl;
    }
    void showDuty() override
    {
        std::cout<<"我是财务处，我负责管钱"<<std::endl;
    }
};

int main(int argc, char** argv)
{
    Company::ptr company(new Company("himile"));
    Financial::ptr financial(new Financial("总部财务部"));
    HumanResouce::ptr humanReco(new HumanResouce("总部人力处"));
    Company::ptr companyQD (new Company("青岛豪迈化工"));
    HumanResouce::ptr humanForQD(new HumanResouce("青岛人力处"));
    companyQD->addDepartment(humanForQD);
    company->addDepartment(companyQD);
    company->addDepartment(financial);
    company->addDepartment(humanReco);
    company->displayDepartment(0);
    return 0;
}